package demo6;

import java.util.ArrayList;
import java.util.List;
import java.util.*;
public class Solution {
    //1.寻找单词
    public String[] findWords(String[] words) {
        List<String> list = new ArrayList<String>();
        String rowIdx = "12210111011122000010020202";
        for (String word : words) {
            boolean isValid = true;
            char idx = rowIdx.charAt(Character.toLowerCase(word.charAt(0)) - 'a');
            for (int i = 1; i < word.length(); ++i) {
                if (rowIdx.charAt(Character.toLowerCase(word.charAt(i)) - 'a') != idx) {
                    isValid = false;
                    break;
                }
            }
            if (isValid) {
                list.add(word);
            }
        }
        String[] ans = new String[list.size()];
        for (int i = 0; i < list.size(); ++i) {
            ans[i] = list.get(i);
        }
        return ans;
    }
    //2.学生出勤记录 I(模拟)
    public boolean checkRecord(String s) {
        int cA = 0;//L计数器
        int cL = 0;//P计数器
        for(int i = 0; i < s.length(); i++){
            char ch = s.charAt(i);
            if(ch == 'A'){
                cA++;
                cL = 0;
                if(cA >= 2){
                    return false;
                }
            }else if(ch == 'L'){
                cL++;
                if(cL >= 3){
                    return false;
                }
            }else {
                cL = 0;
            }
        }
        return true;
    }
    //3.剑指 Offer 58 - I. 翻转单词顺序(倒序分割，trim去掉尾部空格)
    public String reverseWords(String str) {
        String[] strs = str.split(" ");
        StringBuilder ret = new StringBuilder();
        for(int i = strs.length - 1; i >= 0; i--) {
            if(strs[i].equals("")){
                continue;
            }else{
                ret.append(strs[i] + " ");
            }
        }
        return ret.toString().trim();
    }
    //4.划分字母区间(贪心 + 滑动窗口 + map)
    public List<Integer> partitionLabels(String s) {
        List<Integer> ret = new ArrayList<>();
        int[] last = new int[26];
        //map记录每个字母最后一次出现的下标
        for(int i = 0; i < s.length(); i++){
            last[s.charAt(i) - 'a'] = i;
        }
        //滑动窗口
        int left = 0;
        int right = 0;//永远保留区间内，最后一个字母出现的最大值(下标)
        for(int i = 0; i < s.length(); i++) {
            right = Math.max(right, last[s.charAt(i) - 'a']);
            //当区间最大值(下标)等于i时，说明一个区间生成
            if(right == i) {
                ret.add(right - left + 1);
                left = right + 1;
            }
        }
        return ret;
    }
    //5.最大数(贪心 + 排序)
    public String largestNumber(int[] nums) {
        int len = nums.length;
        //贪心+排序
        String[] strSort = new String[len];
        //先将数字转化为字符串
        for(int i = 0; i < len; i++){
            strSort[i] = String.valueOf(nums[i]);
        }
        //重写compareTo方法，修改排序规则，决定时strSort[i]排在前面还是strSort[i + 1]排在前面好
        Arrays.sort(strSort, (a, b) -> {
            String ab = a + b;
            String ba = b + a;
            return ba.compareTo(ab);
        });
        //若拍完后第一个数字是0，那么后面肯定是比0小的数字.返回0即可
        if(strSort[0].equals("0")){
            return "0";
        }
        //将字符串数字进行拼接
        StringBuilder ret = new StringBuilder();
        for(int i = 0; i < len; i++){
            ret.append(strSort[i]);
        }
        return ret.toString();
    }
    //6.剑指 Offer 45. 把数组排成最小的数(贪心 + 排序)
    public String minNumber(int[] nums) {
        int len = nums.length;
        //先将数组转化为字符串数组
        String[] strSort = new String[nums.length];
        for(int i = 0; i < len; i++){
            strSort[i] = String.valueOf(nums[i]);
        }
        //修改排序方法
        Arrays.sort(strSort, (a, b) -> {
            String ab = a + b;
            String ba = b + a;
            return ab.compareTo(ba);
        });
        //拼接起来
        StringBuilder ret = new StringBuilder();
        for(int i = 0; i < len; i++){
            ret.append(strSort[i]);
        }
        return ret.toString();
    }

    //7.剑指 Offer 20. 表示数值的字符串
    public boolean isNumber(String s) {
        if (s == null || s.length() == 0) return false;
        //去掉首位空格
        s = s.trim();
        boolean numFlag = false;
        boolean dotFlag = false;
        boolean eFlag = false;
        for (int i = 0; i < s.length(); i++) {
            //判定为数字，则标记numFlag
            if (s.charAt(i) >= '0' && s.charAt(i) <= '9') {
                numFlag = true;
                //判定为.  需要没出现过.并且没出现过e
            } else if (s.charAt(i) == '.' && !dotFlag && !eFlag) {
                dotFlag = true;
                //判定为e，需要没出现过e，并且出过数字了
            } else if ((s.charAt(i) == 'e' || s.charAt(i) == 'E') && !eFlag && numFlag) {
                eFlag = true;
                numFlag = false;//为了避免123e这种请求，出现e之后就标志为false
                //判定为+-符号，只能出现在第一位或者紧接e后面
            } else if ((s.charAt(i) == '+' || s.charAt(i) == '-') && (i == 0 || s.charAt(i - 1) == 'e' || s.charAt(i - 1) == 'E')) {

                //其他情况，都是非法的
            } else {
                return false;
            }
        }
        return numFlag;
    }
    //8.反转字符串中的元音字母(模拟)
    public String reverseVowels(String s) {
        char[] arr = s.toCharArray();
        //双指针
        int left = 0;
        int right = arr.length - 1;
        //将元音字母用Set存起来
        Set<Character> hash = new HashSet<>();
        setAdd(hash);
        while(left < right) {
            if(!hash.contains(arr[left])){
                left++;
            }
            if(!hash.contains(arr[right])){
                right--;
            }
            if(hash.contains(arr[left]) && hash.contains(arr[right])) {
                char tmp = arr[left];
                arr[left] = arr[right];
                arr[right] = tmp;
                left++;
                right--;
            }
        }
        return String.valueOf(arr);
    }
    private void setAdd(Set<Character> hash) {
        hash.add('a');
        hash.add('A');
        hash.add('e');
        hash.add('E');
        hash.add('i');
        hash.add('I');
        hash.add('o');
        hash.add('O');
        hash.add('u');
        hash.add('U');
    }
    //9.根据字符出现频率排序(哈希表 + 排序)
    public String frequencySort(String s) {
        //哈希表统计次数
        Map<Character, Integer> hash = new HashMap<>();
        for(int i = 0; i < s.length(); i++){
            char ch = s.charAt(i);
            if(!hash.containsKey(ch)) {
                hash.put(ch, 1);
            }else {
                hash.put(ch, hash.get(ch) + 1);
            }
        }
        List<Character> list = new ArrayList<>(hash.keySet());
        Collections.sort(list, (a, b) -> {
            return hash.get(b) - hash.get(a);
        });
        StringBuilder ret = new StringBuilder();
        int size = list.size();
        for (int i = 0; i < size; i++) {
            char c = list.get(i);
            int frequency = hash.get(c);
            for (int j = 0; j < frequency; j++) {
                ret.append(c);
            }
        }
        return ret.toString();
    }
    //10.比较版本号(字符串分割 + 字符串转数字)
    public int compareVersion(String version1, String version2) {
        //思路：字符串分割,对每个区间进行比较
        String[] str1 = version1.split("\\.");//这里是正则表达式
        String[] str2 = version2.split("\\.");
        int len1 = str1.length;
        int len2 = str2.length;
        int p1 = 0;
        int p2 = 0;
        while(p1 < len1 || p2 < len2) {
            int sum1 = 0;
            int sum2 = 0;
            if(p1 < len1) {
                sum1 = Integer.valueOf(str1[p1]);
            }else {
                sum1 = 0;
            }
            if(p2 < len2) {
                sum2 = Integer.valueOf(str2[p2]);
            }else {
                sum2 = 0;
            }
            if(sum1 > sum2) {
                return 1;
            }else if(sum1 < sum2) {
                return -1;
            }else {
                p1++;
                p2++;
            }
        }
        return 0;
    }

}












